﻿// -----------------------------------------------------------------------
// <copyright file="Words_Tools.cs" company="G.W. van der Vegt">
// SharpForth is inspired by JonesForthInC v1.48 and bb4wForth.
// </copyright>
// -----------------------------------------------------------------------

namespace SharpForth
{
    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Collections.Generic;
    using System.Threading;

    /// <summary>
    /// This static class contains all built-in Forth Words.
    /// </summary>
    public static partial class Words
    {
        #region Tools Forth Words

        /// <summary>
        /// 1411 ( --- BUILTIN)
        /// </summary>
        [WordName("FORGET")]
        [WordSet(WordSets.TOOLS_EXT)]
        [Depends("WORD")]
        [Depends("FIND")]
        [Syntax("( \"spaces<name>\" -- )")]
        internal static Lazy<DictionaryEntry> FORGET = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("FORGET", 0, delegate
             {
                 WORD.Value.Invoke();
                 FIND.Value.Invoke();

                 Int32 adr = Forth.PARAM_STACK.Pop();
                 if (adr != -1)
                 {
                     Forth.ForgetMarker(Forth.A2I(adr));
                 }

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// Words
        /// </summary>
        [WordName("WORDS")]
        [WordSet(WordSets.TOOLS)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> WORDS = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("WORDS", 0, delegate
             {
                 foreach (DictionaryEntry de in Forth.Dictionary.ToArray().Reverse())
                 {
                     if ((de.Flags & Forth.FORTH_HIDDEN_MASK) != Forth.FORTH_HIDDEN_MASK)
                     {
                         Forth.DoOutput(String.Format("{0} ", String.IsNullOrEmpty(de.Name) ? Forth.NONAME : de.Name), false);
                     }
                 }

                 Forth.DoOutput(String.Empty, true);

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// 4218
        /// </summary>
        [WordName("SEE")]
        [WordSet(WordSets.TOOLS)]
        [Depends("WORD")]
        [Depends("FIND")]
        [Depends("(SEE)")]
        [Syntax("( \"spaces<name>\" -- )")]
        internal static Lazy<DictionaryEntry> SEE = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("SEE", 0, delegate
             {
                 //! Only when interpreting words interactivly.
                 switch (Forth.STATE)
                 {
                     case Forth.COMPILE_MODE:
                         Debug.Print(Forth.ErrorMarker + "SEE delegate in COMPILE_MODE");
                         break;
                     case Forth.IMMEDIATE_MODE:
                         WORD.Value.Invoke();
                         FIND.Value.Invoke();

                         break;
                 }

                 PAREN_SEE.Value.Invoke();
             }), true);

        /// <summary>
        /// 1545 ( )
        /// </summary>
        [WordName(".S")]
        [WordSet(WordSets.TOOLS)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> DOTS = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry(".S", 0, delegate
             {
                 Forth.DoOutput("(", false);

                 foreach (Int32 s in Forth.PARAM_STACK.ToArray().Reverse())
                 {
                     Forth.DoOutput(" {0}", Forth.DecimalToBase(s, Forth.BASE));
                 }
                 Forth.DoOutput(" ) ", false);

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// 2435
        /// </summary>
        [WordName("BYE")]
        [WordSet(WordSets.TOOLS_EXT)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> BYE = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("BYE", 0, delegate
             {
                 Forth.Shutdown = true;

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// 1545 ( )
        /// </summary>
        [WordName("DUMP")]
        [WordSet(WordSets.TOOLS)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> DUMP = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("DUMP", 0, delegate
             {
                 Int32 len = Forth.POP_P_STACK();
                 Int32 adr = Forth.POP_P_STACK();
                 Byte dat = 0;
                 Int32ByteUnion union = new Int32ByteUnion(0);

                 //! Paint Header
                 Forth.DoOutput("  Addres -");
                 for (Int32 i = 0; i < 8; i++)
                 {
                     Forth.DoOutput(" {0}", i.ToString("X2"));
                 }
                 Forth.DoOutput(" -");
                 for (Int32 i = 8; i < 16; i++)
                 {
                     Forth.DoOutput(" {0}", i.ToString("X2"));
                 }
                 Forth.DoOutput("", true);

                 if (adr % 16 != 0)
                 {
                     Forth.DoOutput("", true);
                     Forth.DoOutput("{0} -", ((adr >> 4) << 4).ToString("X8"));

                     for (Int32 j = 0; j < adr % 16; j++)
                     {
                         Forth.DoOutput(" ".PadRight(3));
                     }
                     if (adr % 16 > 7)
                     {
                         Forth.DoOutput("  ");
                     }
                 }

                 //! Output Dump.
                 //! 01120014 - 2A 2A 2A 2A 2A 2A 2A 2A - 2A 2A 2A 2A 2A 2A 2A 2A
                 for (Int32 i = 0; i < len; i++)
                 {
                     if (adr % 16 == 0)
                     {
                         Forth.DoOutput("", true);
                         Forth.DoOutput("{0} -", ((adr >> 4) << 4).ToString("X8"));
                     }
                     else if (adr % 8 == 0)
                     {
                         Forth.DoOutput(" -");
                     }

                     switch (Forth.A2M(adr))
                     {
                         case Forth.MEM_DEF:
                             union.iVal = Forth.Dictionary[Forth.A2I(adr)].Definition[Forth.A2D(adr)];
                             dat = union[adr % 4];
                             break;
                         case Forth.MEM_RSP:
                             Forth.DoOutput("MemoryType 1 Not Implemented");
                             return;
                         case Forth.MEM_PRM:
                             Forth.DoOutput("MemoryType 2 Not Implemented");
                             return;
                         case Forth.MEM_WRD:
                             dat = (Byte)Forth.STRING_BUFFER[Forth.A2A(adr)];
                             break;
                     }
                     Forth.DoOutput(" {0}", dat.ToString("X2"));

                     adr++;
                 }

                 Forth.DoOutput("", true);

                 Forth.NEXT();
             }), true);

        #endregion Tools Forth Words
    }
}
